package model.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import common.Constants;

import model.LectureService;
import model.Lesson;
import model.LectureServiceListener;
import model.Student;
import model.datasource.DataSource;
import model.datasource.DataSourceFactory;

public class LectureServiceImpl implements LectureService
{
	private static Logger logger = LoggerFactory.getLogger(LectureServiceImpl.class);
	
	private java.util.Collection<LectureServiceListener> listeners;
	private java.util.Collection<Lesson> lessons;
	
	public LectureServiceImpl()
	{
		listeners = new java.util.ArrayList<LectureServiceListener>();
		lessons = new ArrayList<Lesson>();
	}
	
	@Override
	public void addNewLesson(Student s, String title, String content,
			Date date, int income)
	{
		logger.debug(s.getId() + " " + title + " " + content + " " + date );
		
		// TODO Auto-generated method stub
		final DataSource ds = DataSourceFactory.getDataSource();
		final Student ls = s;
		final String ltitle = title;
		final String lcontent = content;
		final Date ldate = date;
		final int lincome = income;
		
		Task t = new Task()
		{			
			@Override
			public void execute()
			{
				// TODO Auto-generated method stub
				Lesson l = ds.addNewLesson(ls, ltitle, lcontent, ldate, lincome);
				java.util.Collection<Lesson> added = new ArrayList<>();
				java.util.Collection<Lesson> removed = new ArrayList<>();
				added.add(l);
				
				lessons.add(l); // add to locally copy of variable
				
				notifyLessonsChanged(added, removed);
			}
		};
		
		ServiceDispatcher.getInstance().enqueue(t);
	}
	
	@Override
	public void addLectureServiceObserver(LectureServiceListener l)
	{
		// TODO Auto-generated method stub
		listeners.add(l);
		
	}
		
	@Override
	public void removeLectureServiceObserver(LectureServiceListener l)
	{
		// TODO Auto-generated method stub
		listeners.remove(l);
		
	}
	
	@Override
	public void deleteLesson(int id)
	{
		logger.debug("delete lesson " + id);
		
		// TODO Auto-generated method stub
		final int lid = id;
		final DataSource ds = DataSourceFactory.getDataSource(); 
		Task t = new Task()
		{
			
			@Override
			public void execute()
			{
				// TODO Auto-generated method stub
				int res = ds.deleteLesson(lid);
				Lesson lessonToRemove = null;
				java.util.Collection<Lesson> added = new ArrayList<>();
				java.util.Collection<Lesson> removed = new ArrayList<>();
				
				if( res == Constants.OK )
				{
					for( Lesson ll : lessons )
					{
						if( ll.getId() == lid )
						{
							removed.add(ll);
							lessonToRemove = ll;
							break;
						}
					}
					lessons.remove(lessonToRemove);
					
					notifyLessonsChanged(added, removed);
				}
			}
		};
		ServiceDispatcher.getInstance().enqueue(t);
	}


	@Override
	public void requestAllLessons()
	{
		// TODO Auto-generated method stub		
		logger.debug("requesting all lessons " );
		
		Task t = new Task()
		{
			
			@Override
			public void execute()
			{
				// TODO Auto-generated method stub
				java.util.Collection<Lesson> added;
				java.util.Collection<Lesson> removed = new ArrayList<>();
				DataSource ds = DataSourceFactory.getDataSource();
				
				added = ds.requestAllLessons();
				lessons = added;
				
				notifyLessonsChanged(added, removed);
			}
		};
		
		ServiceDispatcher.getInstance().enqueue(t);
	}
	
	@Override
	public void updateLesson(int id, Student s, String title, String content,
			Date date, int income)
	{
		// TODO Auto-generated method stub
		final int lid = id;
		final Student ls = s;
		final String ltitle = title;
		final String lcontent = content;
		final Date ldate = date;
		final int lincome = income;
		
		Task t = new Task()
		{
			
			@Override
			public void execute()
			{
				// TODO Auto-generated method stub
				DataSource ds = DataSourceFactory.getDataSource();
				Lesson updatedLesson = ds.updateLesson(lid, ls, ltitle, lcontent, ldate, lincome);
				Collection<Lesson> added = new ArrayList<Lesson>();
				Collection<Lesson> removed = new ArrayList<Lesson>();
				
				added.add(updatedLesson);
				
				notifyLessonsChanged(added, removed);
			}
		};
		
		ServiceDispatcher.getInstance().enqueue(t);
	}
	
	private void notifyLessonsChanged( Collection<Lesson> added, Collection<Lesson> removed)
	{
		logger.debug("notifying...");
		for( LectureServiceListener ll : listeners )
		{
			ll.onLessonsChanged(added, removed);
		}
		logger.debug("notifying done!");
		logger.info("Notifying done");
	}

	@Override
	public void deleteLessons(int[] ids)
	{
		// TODO Auto-generated method stub
		throw new RuntimeException("Not implemented");
	}
}
